package org.ohuang

import com.google.gson.Gson
import org.ohuang.bean.ApkBean
import java.io.File

fun main(args: Array<String>) {
    if (Test.isTest) {
        Test.test()
        return
    }
    runtime(args)

}

private fun runtime(args: Array<String>) {
    if (args.isEmpty()) {
        println("-a  <Config.json path>  输出Config.json")
        println("-b  <Config.json path>  修改包名等信息")
        println("-c  <java.exe path(使用默认请输入''或java)>  <apktool path>  <zipalign path>  <apksigner path> <Config.json path>  smali环境修改包名等信息，并输出apk")
        println("-d  <java.exe path(使用默认请输入''或java)>  <apktool path>  <zipalign path>  <apksigner path> <Config.json path>  <apk path(填写Config.json的apkPath内容无效)>  apk反编译后修改包名等信息，并输出apk")
        println("-e  <java.exe path(使用默认请输入''或java)>  <apktool path>  <zipalign path>  <apksigner path> <Config.json path>   apk反编译后修改包名等信息，并输出apk")
        println("-e1  <java.exe path(使用默认请输入''或java)>  <apktool path>  <zipalign path>  <apksigner path> <Config.json path>  apk不解资源反编译后 修改包名和flag 并输出apk")
        println("-m  <path1 框架smali>  <path2 apkSmali>   打广告框架")
        println("-m1  <path1 框架smali>  <path2 apkSmali>   打广告框架(资源冲突框架优先)")
        println("-channel <apktool path>  <java.exe path(使用默认请输入''或java)>   <apksigner path> <zipalign path>  <channel.json path>   生成多渠道")
        println("-cjs  <channel.json path>  输出channel.json")

    } else {
        var s = args[0]

        when (s) {
            "-a" -> {
                var path1 = args[1].replace("\"", "").replace("'", "")
                println("path1=$path1")
                outConfig(File(path1))
            }

            "-b" -> {
                var path1 = args[1].replace("\"", "").replace("'", "")
                println("path1=$path1")
                var file = File(path1)
                var apkBean = getApkBean(file)

                setAbsolutePath(apkBean, file.parentFile.absolutePath + "/")
                println(apkBean)
                replaceApk(apkBean)
            }

            "-c" -> {

                var path1 = args[1].replace("\"", "").replace("'", "")
                var path2 = args[2].replace("\"", "").replace("'", "")
                var path3 = args[3].replace("\"", "").replace("'", "")
                var path4 = args[4].replace("\"", "").replace("'", "")
                var path5 = args[5].replace("\"", "").replace("'", "")
                println("path1=$path1")
                println("path2=$path2")
                println("path3=$path3")
                println("path4=$path4")
                println("path5=$path5")
                replaceAnd2Apk(path1, path2, path3, path4, path5)
            }

            "-d" -> {

                var path1 = args[1].replace("\"", "").replace("'", "")
                var path2 = args[2].replace("\"", "").replace("'", "")
                var path3 = args[3].replace("\"", "").replace("'", "")
                var path4 = args[4].replace("\"", "").replace("'", "")
                var path5 = args[5].replace("\"", "").replace("'", "")
                var path6 = args[6].replace("\"", "").replace("'", "")
                println("path1=$path1")
                println("path2=$path2")
                println("path3=$path3")
                println("path4=$path4")
                println("path5=$path5")
                println("path6=$path6")
                apk2replaceAnd2Apk(path1, path2, path3, path4, path5, path6)
            }

            "-e" -> {
                var path1 = args[1].replace("\"", "").replace("'", "")
                var path2 = args[2].replace("\"", "").replace("'", "")
                var path3 = args[3].replace("\"", "").replace("'", "")
                var path4 = args[4].replace("\"", "").replace("'", "")
                var path5 = args[5].replace("\"", "").replace("'", "")

                println("path1=$path1")
                println("path2=$path2")
                println("path3=$path3")
                println("path4=$path4")
                println("path5=$path5")

                apk2replaceAnd2ApkForConfigNotAbsolutePath(path1, path2, path3, path4, path5)
            }

            "-e1" -> {

                var path1 = args[1].replace("\"", "").replace("'", "")
                var path2 = args[2].replace("\"", "").replace("'", "")
                var path3 = args[3].replace("\"", "").replace("'", "")
                var path4 = args[4].replace("\"", "").replace("'", "")
                var path5 = args[5].replace("\"", "").replace("'", "")

                println("path1=$path1")
                println("path2=$path2")
                println("path3=$path3")
                println("path4=$path4")
                println("path5=$path5")

                apk2replaceAnd2ApkForConfigNotEncodeRes(path1, path2, path3, path4, path5)
            }

            "-m" -> {
                var path1 = args[1].replace("\"", "").replace("'", "")
                var path2 = args[2].replace("\"", "").replace("'", "")
                println("path1=$path1")
                println("path2=$path2")
                mergeApk(path1, path2)
            }

            "-m1" -> {
                //-a  <path1>  <path2>   合并apk反编译环境
                var path1 = args[1].replace("\"", "").replace("'", "")
                var path2 = args[2].replace("\"", "").replace("'", "")
                println("path1=$path1")
                println("path2=$path2")
                mergeApk2(path1, path2)
            }

            "-cjs" -> {
                var path1 = args[1].replace("\"", "").replace("'", "")
                println("path1=$path1")
                ChannelUtil.outConfig(File(path1))
            }

            "-channel" -> {
                var path1 = args[1].replace("\"", "").replace("'", "")
                var path2 = args[2].replace("\"", "").replace("'", "")
                var path3 = args[3].replace("\"", "").replace("'", "")
                var path4 = args[4].replace("\"", "").replace("'", "")
                var path5 = args[5].replace("\"", "").replace("'", "")
                println("path1=$path1")
                println("path2=$path2")
                println("path3=$path3")
                println("path4=$path4")
                println("path5=$path5")
                ChannelUtil.start(path1, path2, path3,path4,path5)
            }
        }
    }
}


private fun apk2replaceAnd2ApkForConfigNotAbsolutePath(
    javaexe: String?,
    apktool: String,
    zipalign: String,
    apksigner: String,
    configFile: String
) {

    var file = File(configFile)
    var gson = Gson()
    var readText = readText(file)
    var fromJson: ApkBean = ApkBean()
    tryCatch("${file.name} 内容不符合json格式") {
        fromJson = gson.fromJson(readText, ApkBean::class.java)
    }
    var rootPath1 = file.parentFile.absolutePath + "/"
    setAbsolutePath(fromJson, rootPath1)

    println(fromJson)

    if (fromJson.apkPath.isNullOrEmpty()) {
        println("没有配置apkPath路径")
        return
    } else {
        apkToSmali(javaexe, apktool, apkBean = fromJson, fromJson.apkPath)
    }
    replaceApk(fromJson)
    smaliToApk(javaexe, apktool, zipalign, apksigner, fromJson)
}

private fun apk2replaceAnd2ApkForConfigNotEncodeRes(
    javaexe: String?,
    apktool: String,
    zipalign: String,
    apksigner: String,
    configFile: String
) {

    var file = File(configFile)
    var gson = Gson()
    var readText = readText(file)
    var fromJson: ApkBean = ApkBean()
    tryCatch("${file.name} 内容不符合json格式") {
        fromJson = gson.fromJson(readText, ApkBean::class.java)
    }
    var rootPath1 = file.parentFile.absolutePath + "/"
    setAbsolutePath(fromJson, rootPath1)

    println(fromJson)

    if (fromJson.apkPath.isNullOrEmpty()) {
        println("没有配置apkPath路径")
        return
    } else {
        apkToSmaliNoEncodeRes(javaexe, apktool, apkBean = fromJson, fromJson.apkPath)
    }
    replacePackageNameAndFlag(fromJson)
    smaliToApk(javaexe, apktool, zipalign, apksigner, fromJson)
}

private fun replaceAnd2Apk(javaexe: String?, apktool: String, zipalign: String, apksigner: String, configFile: String) {
    var file = File(configFile)
    var gson = Gson()
    var readText = readText(file)
    var fromJson = gson.fromJson(readText, ApkBean::class.java)
    var rootPath1 = file.parentFile.absolutePath + "/"
    setAbsolutePath(fromJson, rootPath1)
    println(fromJson)
    replaceApk(fromJson)
    smaliToApk(javaexe, apktool, zipalign, apksigner, fromJson)
}

private fun setAbsolutePath(fromJson: ApkBean, rootPath: String) {
    var rootPath1 = rootPath;
    if (rootPath.endsWith("/") || rootPath.endsWith("\\")) {

    } else {
        rootPath1 = "$rootPath/"
    }
    if (fromJson.apkPath.isNotEmpty() && !fromJson.apkPath.contains(":")) {//如果不是绝对路径
        fromJson.apkPath = rootPath1 + fromJson.apkPath
    }
    if (fromJson.smaliPath.isNotEmpty() && !fromJson.smaliPath.contains(":")) {
        fromJson.smaliPath = rootPath1 + fromJson.smaliPath
    }
    if (fromJson.signingPath.isNotEmpty() && !fromJson.signingPath.contains(":")) {
        fromJson.signingPath = rootPath1 + fromJson.signingPath
    }
    if (fromJson.icon.isNotEmpty() && !fromJson.icon.contains(":")) {
        fromJson.icon = rootPath1 + fromJson.icon
    }
}

private fun apk2replaceAnd2Apk(
    javaexe: String?,
    apktool: String,
    zipalign: String,
    apksigner: String,
    configFile: String,
    apkPath: String
) {

    var file = File(configFile)
    var gson = Gson()
    var readText = readText(file)
    var fromJson: ApkBean = ApkBean()
    tryCatch("${file.name} 内容不符合json格式") {
        fromJson = gson.fromJson(readText, ApkBean::class.java)
    }
    setAbsolutePath(fromJson, file.parent + "/")
    println(fromJson)
    if (apkPath.isEmpty()) {
        if (fromJson.apkPath.isNullOrEmpty()) {
            println("没有配置apkPath路径")
            return
        } else {
            apkToSmali(javaexe, apktool, apkBean = fromJson, fromJson.apkPath)
        }
    } else {
        apkToSmali(javaexe, apktool, apkBean = fromJson, apkPath)
    }
    replaceApk(fromJson)
    smaliToApk(javaexe, apktool, zipalign, apksigner, fromJson)
}

private fun apkToSmaliNoEncodeRes(javaexe: String?, apktool: String, apkBean: ApkBean, apkPath: String) {
    println("开始反编译")
    var file = File(apkBean.smaliPath)
    if (file.exists()) {
        println("删除文件${file.name}")
        var delete = FileUtils.delete(file)
        if (delete) {
            println("删除成功")
        } else {
            println("删除失败")
        }
    }
    var java: String = if (javaexe.isNullOrEmpty()) {
        "java"
    } else {
        javaexe.replace(" ", "\" \"")
    }
    val cmd =
        "$java -Dfile.encoding=utf-8 -jar  \"$apktool\" d  \"$apkPath\"  -o \"${apkBean.smaliPath}\" -f --no-res"
    println(cmd)
    var arrayOf = arrayOf(
        "cmd.exe", "/c", cmd
    )

    var exec = ExecUtil.execAndPrint(
        arrayOf,
        30 * 60
    )
    println(exec)

}

private fun apkToSmali(javaexe: String?, apktool: String, apkBean: ApkBean, apkPath: String) {
    println("开始反编译")
    var file = File(apkBean.smaliPath)
    if (file.exists()) {
        println("删除文件${file.name}")
        var delete = FileUtils.delete(file)
        if (delete) {
            println("删除成功")
        } else {
            println("删除失败")
        }
    }
    var java: String = if (javaexe.isNullOrEmpty()) {
        "java"
    } else {
        javaexe.replace(" ", "\" \"")
    }
    val cmd =
        "$java -Dfile.encoding=utf-8 -jar  \"$apktool\" d --only-main-classes \"$apkPath\"  -o \"${apkBean.smaliPath}\" -f"
    println(cmd)
    var arrayOf = arrayOf(
        "cmd.exe", "/c", cmd
    )

    var exec = ExecUtil.execAndPrint(
        arrayOf,
        30 * 60
    )
    println(exec)

}

private fun smaliToApk(javaexe: String?, apktool: String, zipalign: String, apksigner: String, apkBean: ApkBean) {
    toApk(javaexe, apkBean, apktool)
    toZipalign(apkBean, zipalign)
    toSigner(javaexe, apksigner, apkBean)
}


private fun toSigner(javaexe: String?, apksigner: String, apkBean: ApkBean) {
    println("开始签名")
    var file = File(apkBean.smaliPath + "-sign.apk")
    if (file.exists()) {
        println("删除文件${file.name}")
        var delete = file.delete()
        if (delete) {
            println("删除成功")
        } else {
            println("删除失败")
        }
    }
    var java: String = if (javaexe.isNullOrEmpty()) {
        "java"
    } else {
        javaexe.replace(" ", "\" \"")
    }


    val cmd =
        "$java -Dfile.encoding=utf-8 -jar  \"$apksigner\" sign  --in  \"${apkBean.smaliPath + "/temp1-align.apk"}\"  " +
                "--out \"${file.absolutePath}\" --v1-signing-enabled true --v2-signing-enabled true --v3-signing-enabled true --ks  " +
                "\"${apkBean.signingPath}\"  --ks-pass pass:\"${apkBean.passWord}\" --ks-key-alias \"${apkBean.alias}\""
    println(cmd)
    var execAndPrint = ExecUtil.execAndPrint(
        arrayOf(
            "cmd.exe", "/c", cmd
        ),
        30 * 60
    )


    println(execAndPrint)
}

private fun toZipalign(apkBean: ApkBean, zipalign: String) {
    println("开始资源文件对齐")
    var file = File(apkBean.smaliPath + "/temp1-align.apk")
    if (file.exists()) {
        println("删除文件${file.name}")
        var delete = file.delete()
        if (delete) {
            println("删除成功")
        } else {
            println("删除失败")
        }
    }
    val cmd =
        "${zipalign.replace(" ", "\" \"")}  -f -v 4 \"${apkBean.smaliPath + "/temp1.apk"}\"  \"${file.absolutePath}\""
    println(cmd)
    var arrycmd = arrayOf("cmd.exe", "/c", cmd)
    var exec = ExecUtil.execAndPrint(
        arrycmd,
        10 * 60, "Verification succesful"
    )
    println(exec)
}

private fun toApk(javaexe: String?, apkBean: ApkBean, apktool: String) {
    println("开始生成apk")
    var file = File(apkBean.smaliPath + "/temp1.apk")
    if (file.exists()) {
        println("删除文件${file.name}")
        var delete = file.delete()
        if (delete) {
            println("删除成功")
        } else {
            println("删除失败")
        }
    }
    var java = if (javaexe.isNullOrEmpty()) {
        "java"
    } else {
        javaexe.replace(" ", "\" \"")
    }


    val cmd =
        "$java -Dfile.encoding=utf-8 -jar \"$apktool\" b \"${apkBean.smaliPath}\" -o \"${file.absolutePath}\""
    println(cmd)
    var execAndPrint = ExecUtil.execAndPrint(arrayOf("cmd.exe", "/c", cmd), 30 * 60)


    println(execAndPrint)
}